package com.koomii.redismq;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Pipeline;
import redis.clients.util.Pool;

/**
 * Redis操作工具
 * @author lizongyue
 *
 */
public class RedisUtil {
	/**
	 * 日志
	 */
	private static final Log logger = LogFactory.getLog(RedisUtil.class);
	
	
	public RedisUtil(Pool<Jedis> pool) {
		super();
		this.pool = pool;
	}

	/**
	 * REDIS连接池
	 */
	private volatile Pool<Jedis> pool;

	/**
	 * 从连接池获得一个redis连接
	 * 
	 * @return
	 */
	public Jedis getConnent() {
		Jedis jedis = pool.getResource();
		return jedis;
	}

	/**
	 * 关闭当前连接实例，将连接返回连接池
	 * 
	 * @param jedis  redis连接实例
	 */
	public void close(Jedis jedis) {
		try {
			if (jedis != null) {
				jedis.close();
			}
		} catch (Exception e) {
			logger.error("close jedis failed!", e);
		}
	}
	
	/**
	 * 删除指定的key
	 * @param key
	 * @return
	 */
	public Long del(String key) {
		Jedis jedis = null;

		try {
			jedis = getConnent();
			return jedis.del(key);
		} catch (Exception e) {
			logger.error("redis get data failed!", e);
		} finally {
			close(jedis);
		}
		return null;
	}

	/**
	 * 阻塞获取数据
	 *
	 * @param key redis键
	 * @param waitSeconds 等待时间
	 * @param clazz 序列化模型类
	 * @return
	 */
	public <T> T blpop(String key, int waitSeconds, Class<T> clazz) {
		Jedis jedis = null;

		try {
			jedis = getConnent();
			List<byte[]> values = jedis.blpop(waitSeconds, key.getBytes());

			if (values != null && values.size() > 0) {
				byte[] value = values.get(1);
				return ConvertUtil.unserialize(value, clazz);
			} else {
				return null;
			}
		} catch (Exception e) {
			logger.error("redis get data failed!", e);
			return null;
		} finally {
			close(jedis);
		}
	}

	/**
	 * 存储REDIS队列 顺序存储,可设置过期时间，过期时间以秒为单位
	 * 
	 * @param key reids键名
	 * @param value 键值
	 * @param second 过期时间(秒)
	 */
	public <T> Long rpush(String key, T value, int second) {
		Jedis jedis = null;
		Long ret = null;
		try {
			jedis = getConnent();
			byte[] bytes = ConvertUtil.serialize(value);
			ret = jedis.rpush(key.getBytes(), bytes);

			if (second > 0) {
				jedis.expire(key, second);
			}

		} catch (Exception e) {
			logger.error("redis lpush data failed , key = " + key, e);
		} finally {
			close(jedis);
		}

		return ret;
	}
	
	/**
	 * 存储REDIS队列 顺序存储,可设置过期时间，过期时间以秒为单位
	 * 
	 * @param map redis键值对
	 * @param second 过期时间(秒)
	 */
	public <T> void rpushGroup(Map<String, T> map, int second) {
		Jedis jedis = null;
		try {
			jedis = getConnent();
			//使用pipline
			Pipeline pipeline = jedis.pipelined();
			for(String key:map.keySet()) {
				byte[] bytes = ConvertUtil.serialize(map.get(key));
				pipeline.rpush(key.getBytes(), bytes);
				
				if (second > 0) {
					pipeline.expire(key, second);
				}
			}
			//执行pipline
			pipeline.sync();
		} catch (Exception e) {
			logger.error("redis lpush data failed , keys = " + map.keySet(), e);
		} finally {
			close(jedis);
		}
	}

	/**
	 * 获取存储REDIS队列长度
	 *
	 * @param key reids键名
	 */
	public Long llen(String key) {
		Jedis jedis = null;
		Long ret = null;
		try {
			jedis = getConnent();
			return jedis.llen(key);

		} catch (Exception e) {
			logger.error("redis llen data failed , key = " + key, e);
		} finally {
			close(jedis);
		}

		return ret;
	}

	/**
	 * 存储redis set集合，无序
	 * 
	 * @param key reids键名
	 * @param value 值
	 * @return
	 */
	public Long sadd(String key, String value) {
		Jedis jedis = null;
		Long ret = null;
		try {
			jedis = getConnent();
			ret = jedis.sadd(key, value);
		} catch (Exception e) {
			logger.error("redis sadd data failed , key = " + key, e);
		} finally {
			close(jedis);
		}

		return ret;
	}
	
	/**
	 * 查询redis set集合
	 * 
	 * @param key reids键名
	 * @return
	 */
	public Set<String> smembers(String key) {
		Jedis jedis = null;
		Set<String> ret = null;
		try {
			jedis = getConnent();
			ret = jedis.smembers(key);
		} catch (Exception e) {
			logger.error("redis smembers failed , key = " + key, e);
		} finally {
			close(jedis);
		}
		return ret;
	}
	
	/**
	 * 删除
	 * 
	 * @param key reids键名
	 * @param memeber 成员
	 * @return
	 */
	public Long srem(String key,String memeber) {
		Jedis jedis = null;
		Long ret = null;
		try {
			jedis = getConnent();
			ret = jedis.srem(key, memeber);
		} catch (Exception e) {
			logger.error("redis srem failed , key = " + key, e);
		} finally {
			close(jedis);
		}

		return ret;
	}
	
	/**
	 * hset inc增长，减少时value传负数
	 * @param key
	 * @param field
	 * @param value
	 * @return
	 */
	public Long hincrby(String key,String field,Long value) {
		Jedis jedis = null;
		Long ret = null;
		try {
			jedis = getConnent();
			ret = jedis.hincrBy(key, field, value);
		} catch (Exception e) {
			logger.error("redis hincrBy failed , key = " + key+",field="+field, e);
		} finally {
			close(jedis);
		}
		return ret;
	}
	
	/**
	 * 获取key中所有的field和value
	 * @param key
	 * @return
	 */
	public Map<String, String> hgetAll(String key) {
		Jedis jedis = null;
		Map<String, String> ret = null;
		try {
			jedis = getConnent();
			ret = jedis.hgetAll(key);
		} catch (Exception e) {
			logger.error("redis hincrBy failed , key = " + key, e);
		} finally {
			close(jedis);
		}
		return ret;
	}
	
	/**
	 * hset设置Hash
	 * @param key
	 * @param field
	 * @param value
	 * @return
	 */
	public Long hset(String key,String field,String value) {
		Jedis jedis = null;
		Long ret = null;
		try {
			jedis = getConnent();
			ret = jedis.hset(key, field, value);
		} catch (Exception e) {
			logger.error("redis hset failed , key = " + key+",field="+field, e);
		} finally {
			close(jedis);
		}
		return ret;
	}
	
}
